<template>
    <div class="common-tree comp-article-of-tags" v-loading.fullscreen="loading">
        <div class="common-tree__nect" v-show="$slots.head || $scopedSlots.head">
            <slot name="head" :loading="loading" :filters="filters" :selects="selects"></slot>
        </div>
        <div class="common-tree__body" ref="scroller">
            <div class="item item--lv0">
                <div class="name">分类名称</div>
                <div class="space" v-show="$slots.body || $scopedSlots.body">操作</div>
            </div>
            <template v-for="tag1 in list">
                <div class="item item--lv1" :key="tag1.id" :class="{ expanded: tag1.expanded, selected: tag1.selected }" @click="expandTag(tag1)" @mouseenter="activateTag(tag1)" @mouseleave="activateTag(tag1)">
                    <div class="name">
                        <div class="expand"></div>
                        <div class="text">{{ tag1.name }}</div>
                    </div>
                    <div class="space" v-show="$slots.body || $scopedSlots.body">
                        <slot name="body" :loading="loading" :filters="filters" :data="tag1" :selects="selects" v-if="tag1.activated"></slot>
                    </div>
                </div>
                <template v-for="tag2 in tag1.tags">
                    <div class="item item--lv2" :key="tag2.id" :class="{ expanded: tag2.expanded, selected: tag2.selected }" @click="expandTag(tag2)" @mouseenter="activateTag(tag2)" @mouseleave="activateTag(tag2)" v-if="tag1.expanded">
                        <div class="name">
                            <div class="expand"></div>
                            <div class="selector" @click.stop="selectTag(tag2)" v-if="select"></div>
                            <div class="text" @click.stop="selectTag(tag2)">{{ tag2.name }}</div>
                        </div>
                        <div class="space" v-show="$slots.body || $scopedSlots.body">
                            <slot name="body" :loading="loading" :filters="filters" :data="tag2" :selects="selects" v-if="tag2.activated"></slot>
                        </div>
                    </div>
                </template>
            </template>
        </div>
        <div class="common-tree__foot" v-show="$slots.foot || $scopedSlots.foot">
            <slot name="foot" :loading="loading" :filters="filters" :selects="selects"></slot>
        </div>
    </div>
</template>

<script>
    import mixin from "../mixin";
    import { object, array, string, int, session } from "../util";
    export default {
        name: "comp-article-of-tags",
        mixins: [mixin],
        props: {
            expanded: { type: Boolean, default: false },
            select: { type: Boolean, default: false },
            link: { type: Boolean, default: false },
        },
        data: () => ({
            loading: false,
            filters: {
                linage: 1000,
                page: 1,
                total: 0,
            },
            list: [],
            selects: [],
            expands: [],
            scrollTop: 0,
        }),
        methods: {
            reset(deep) {
                let data = deep ? {} : object(session([this.env.key, this.$options.name, "filters", this.$route.fullPath]));
                this.filters = Object.assign(this.$options.data().filters, data);
                this.expands = deep ? [] : array(session([this.env.key, this.$options.name, "expands", this.$route.fullPath]));
                this.scrollTop = deep ? 0 : this.$refs.scroller.scrollTop;
                this.search(true);
            },
            validate() {
                let filters = this.filters;
                let expands = this.expands;
                filters.total = Math.max(int(filters.total), 0);
                filters.linage = Math.max(int(filters.linage), 1);
                filters.page = Math.max(Math.min(int(filters.page), Math.ceil(filters.total / filters.linage)), 1);
                session([this.env.key, this.$options.name, "filters", this.$route.fullPath], filters);
                session([this.env.key, this.$options.name, "expands", this.$route.fullPath], expands);
            },
            search(clean) {
                if (this.loading) return;
                if (clean) this.list = [];
                if (clean) this.selects = [];
                let filters = this.filters;
                this.validate();
                this.loading = true;
                this.plugins.user.getArticleOfTags(filters).then((res) => {
                    this.loading = false;
                    this.list = [];
                    this.selects = [];
                    if (res.code === 0) {
                        let data = res.data;
                        let tags = data.list.reduce((tags, tag) => {
                            if (tag.id) tags[tag.id] = tag;
                            return tags;
                        }, {});
                        let sort = (tag) => tag.tag.id ? sort(tags[tag.tag.id]) + 1 : 1;
                        let flat = (tag) => [tag, ...tag.tags.map(flat)].flat();
                        for (let tag of data.list) {
                            tag.level = sort(tag);
                        }
                        for (let tag of data.list) {
                            if (tag.level === 1) continue;
                            let parent = tags[tag.tag.id];
                            if (parent) parent.tags.push(tag);
                            if (parent) tag.tag.name = parent.name;
                        }
                        for (let tag of data.list) {
                            let expand = this.expands.find((data) => data.key === tag.id);
                            if (expand) tag.expanded = expand.value;
                            else if (tag.level === 1 || tag.tags.length === 0) tag.expanded = this.expanded;
                        }
                        filters.total = 0;
                        this.list = data.list.filter((tag) => tag.level === 1);
                        this.validate();
                        this.$nextTick(() => this.$refs.scroller.scrollTop = this.scrollTop);
                    } else {
                        filters.total = 0;
                        this.validate();
                        this.$nextTick(() => this.$refs.scroller.scrollTop = this.scrollTop);
                        this.plugins.modal.toast("列表加载失败<br>" + res.code + "：" + res.msg, "error");
                    }
                });
            },
            activateTag(tag) {
                tag.activated = !tag.activated;
            },
            expandTag(tag) {
                tag.expanded = !tag.expanded;
                let index = this.expands.findIndex((data) => data.key === tag.id);
                if (index > -1) this.expands.splice(index, 1);
                this.expands.push({ key: tag.id, value: tag.expanded });
                this.validate();
            },
            selectTag(tag) {
                let select = (tags, selects) => tags.reduce((selects, tag) => {
                    if (tag.selected) selects.push(tag);
                    return select(tag.tags, selects);
                }, selects);
                if (this.select) {
                    tag.selected = !tag.selected;
                    this.selects = select(this.list, []);
                } else {
                    this.selects = [];
                    this.expandTag(tag);
                }
            },
            init() {
                this.loading = false;
                this.reset();
            },
        },
    };
</script>

<style lang="scss">
    .comp-article-of-tags {
        overflow: hidden;
    }
</style>